home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume11 / tinymud2 / part05 < prev    next >
Encoding:
Internet Message Format  |  1990-08-10  |  54.6 KB

  1. Path: uunet!ogicse!zephyr.ens.tek.com!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v11i009:  tinymud2 - user-extendible multi-user adventure (v1.5.4), Part05/10
  5. Message-ID: <6054@tekred.CNA.TEK.COM>
  6. Date: 30 Jul 90 16:45:30 GMT
  7. Sender: news@tekred.CNA.TEK.COM
  8. Lines: 2211
  9. Approved: billr@saab.CNA.TEK.COM
  10. Posted: Mon Jul 30 09:45:30 1990
  11.  
  12. Submitted-by: James Aspnes <asp@cs.cmu.edu>
  13. Posting-number: Volume 11, Issue 9
  14. Archive-name: tinymud2/Part05
  15. Supersedes: tinymud: Volume 8, Issue 80-83
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 5 (of 10)."
  26. # Contents:  interface.c joinspl.sh wiz.c
  27. # Wrapped by billr@saab on Fri Jul 27 15:27:46 1990
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'interface.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'interface.c'\"
  31. else
  32. echo shar: Extracting \"'interface.c'\" \(33958 characters\)
  33. sed "s/^X//" >'interface.c' <<'END_OF_FILE'
  34. X/* Concentrator upgraded June 1990 Robert Hood */
  35. X
  36. X/* modifed Concentrator to match Fuzzy & Randoms 1.5.4 changes = 6/90 Fuzzy */
  37. X
  38. X/* modified interface.c to support LOTS of people, using a concentrator */
  39. X/* May 1990, Robert Hood */
  40. X
  41. X/* #define CHECKC    /* consistency checking */
  42. X
  43. X#include <stdio.h>
  44. X#include <sys/param.h>
  45. X#include <sys/types.h>
  46. X#include <sys/file.h>
  47. X#include <sys/time.h>
  48. X#include <signal.h>
  49. X#include <sys/ioctl.h>
  50. X#include <sys/wait.h>
  51. X#include <fcntl.h>
  52. X#include <sys/errno.h>
  53. X#include <ctype.h>
  54. X#include <sys/socket.h>
  55. X#include <netinet/in.h>
  56. X#include <netdb.h>
  57. X
  58. X#include "config.h"
  59. X#include "db.h"
  60. X#include "interface.h"
  61. X
  62. X#define BUFSIZE 0xFFFF
  63. X
  64. Xstruct text_block
  65. X{
  66. X  int             nchars;
  67. X  struct text_block *nxt;
  68. X  char           *start;
  69. X  char           *buf;
  70. X};
  71. X
  72. Xstruct text_queue
  73. X{
  74. X  struct text_block *head;
  75. X  struct text_block **tail;
  76. X};
  77. X
  78. Xstruct descriptor_data
  79. X{
  80. X  int             descriptor;
  81. X  int             num;
  82. X  int             connected;
  83. X  dbref           player;
  84. X  char           *output_prefix;
  85. X  char           *output_suffix;
  86. X  int             output_size;
  87. X  struct text_queue output;
  88. X  struct text_queue input;
  89. X  char           *raw_input;
  90. X  char           *raw_input_at;
  91. X  long            connected_at;
  92. X  long            last_time;
  93. X  int             quota;
  94. X  struct sockaddr_in address;           /* added 3/6/90 SCG */
  95. X  char           *hostname;           /* 5/18/90 - Fuzzy */
  96. X  struct descriptor_data *next;
  97. X};
  98. X
  99. X#define MALLOC(result, type, number) do {            \
  100. X    if (!((result) = (type *) malloc ((number) * sizeof (type))))    \
  101. X        panic("Out of memory");                \
  102. X    } while (0)
  103. X
  104. X#define FREE(x) (free((void *) x))
  105. X
  106. Xstruct message
  107. X{
  108. X  char           *data;
  109. X  short           len;
  110. X  struct message *next;
  111. X};
  112. X
  113. Xstruct conc_list
  114. X{
  115. X  struct conc_list *next;
  116. X  int             sock, current, status;
  117. X  struct descriptor_data *firstd;
  118. X  struct message *first, *last;
  119. X  char           *incoming, *outgoing;
  120. X  int             ilen, olen;
  121. X}              *firstc = 0;
  122. X
  123. Xvoid            queue_message(struct conc_list * c, char *data, int len);
  124. Xvoid            start_log();
  125. Xstruct timeval  timeval_sub(struct timeval now, struct timeval then);
  126. Xstruct timeval  msec_add(struct timeval t, int x);
  127. Xstruct timeval  update_quotas(struct timeval last, struct timeval current);
  128. Xvoid            main_loop();
  129. Xint             notify(dbref player, const char *msg);
  130. Xvoid            process_output(struct conc_list * c);
  131. Xint             process_input(struct descriptor_data * d, char *buf, int got);
  132. Xvoid            process_commands();
  133. Xvoid            dump_users(struct descriptor_data * e, char *user);
  134. Xvoid            free_text_block(struct text_block * t);
  135. Xvoid            main(int argc, char **argv);
  136. Xvoid            set_signals();
  137. Xint             msec_diff(struct timeval now, struct timeval then);
  138. Xvoid            clearstrings(struct descriptor_data * d);
  139. Xvoid            shutdownsock(struct descriptor_data * d);
  140. Xstruct descriptor_data *initializesock(struct sockaddr_in * a);
  141. Xstruct text_block *make_text_block(const char *s, int n);
  142. Xvoid            add_to_queue(struct text_queue * q, const char *b, int n);
  143. Xint             flush_queue(struct text_queue * q, int n);
  144. Xint             queue_write(struct descriptor_data * d, const char *b, int n);
  145. Xint             queue_string(struct descriptor_data * d, const char *s);
  146. Xvoid            freeqs(struct descriptor_data * d);
  147. Xvoid            welcome_user(struct descriptor_data * d);
  148. Xvoid            do_motd(dbref);
  149. Xchar           *strsave(const char *s);
  150. Xvoid            save_command(struct descriptor_data * d, const char *command);
  151. Xvoid            set_userstring(char **userstring, const char *command);
  152. Xint             do_command(struct descriptor_data * d, char *command);
  153. Xvoid            check_connect(struct descriptor_data * d, const char *msg);
  154. Xvoid            parse_connect(const char *msg, char *command, char *user, char *pass);
  155. Xvoid            close_sockets();
  156. Xvoid            emergency_shutdown(void);
  157. Xvoid            boot_off(dbref player);
  158. Xint             bailout(int sig, int code, struct sigcontext * scp);
  159. Xchar           *time_format_1(long dt);
  160. Xchar           *time_format_2(long dt);
  161. X#ifdef CONNECT_MESSAGES
  162. Xvoid            announce_connect(dbref);
  163. Xvoid            announce_disconnect(dbref);
  164. X#endif                       /* CONNECT_MESSAGES */
  165. Xint             sigshutdown(int, int, struct sigcontext *);
  166. X
  167. Xint             logsynch();
  168. Xchar           *logfile = LOG_FILE;
  169. X
  170. Xint             debug;
  171. Xvoid            chg_userid();
  172. Xvoid            file_date(struct descriptor_data * d, const char *file);
  173. X
  174. Xstatic const char *connect_fail = "Either that player does not exist, or has a different password.\n";
  175. X#ifndef REGISTRATION
  176. Xstatic const char *create_fail = "Either there is already a player with that name, or that name is illegal.\n";
  177. X#endif                       /* REGISTRATION */
  178. Xstatic const char *flushed_message = "<Output Flushed>\n";
  179. Xstatic const char *shutdown_message = "Going down - Bye\n";
  180. X
  181. Xint             sock;
  182. Xint             shutdown_flag = 0;
  183. X
  184. Xint             port = TINYPORT;
  185. Xint             intport = INTERNAL_PORT;
  186. X
  187. X
  188. Xstart_port()
  189. X{
  190. X  int             temp;
  191. X  struct sockaddr_in sin;
  192. X
  193. X  sock = socket(AF_INET, SOCK_STREAM, 0);
  194. X  if (sock < 1)
  195. X  {
  196. X    perror("socket");
  197. X    exit(-1);
  198. X  }
  199. X  temp = 1;
  200. X  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&temp, sizeof(temp));
  201. X  sin.sin_family = AF_INET;
  202. X  sin.sin_port = htons(intport);
  203. X  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  204. X
  205. X  temp = bind(sock, (struct sockaddr *) & sin, sizeof(sin));
  206. X  if (temp < 0)
  207. X  {
  208. X    perror("bind");
  209. X    exit(-1);
  210. X  }
  211. X  temp = listen(sock, 5);
  212. X  if (temp < 0)
  213. X  {
  214. X    perror("listen");
  215. X    exit(-1);
  216. X  }
  217. X}
  218. X
  219. Xstruct timeval
  220. X                timeval_sub(struct timeval now, struct timeval then)
  221. X{
  222. X                  now.tv_sec -= then.tv_sec;
  223. X  now.tv_usec -= then.tv_usec;
  224. X  if (now.tv_usec < 0)
  225. X  {
  226. X    now.tv_usec += 1000000;
  227. X    now.tv_sec--;
  228. X  }
  229. X  return now;
  230. X}
  231. X
  232. Xstruct timeval
  233. X                msec_add(struct timeval t, int x)
  234. X{
  235. X                  t.tv_sec += x / 1000;
  236. X  t.tv_usec += (x % 1000) * 1000;
  237. X  if (t.tv_usec >= 1000000)
  238. X  {
  239. X    t.tv_sec += t.tv_usec / 1000000;
  240. X    t.tv_usec = t.tv_usec % 1000000;
  241. X  }
  242. X  return t;
  243. X}
  244. X
  245. Xstruct timeval
  246. X                update_quotas(struct timeval last, struct timeval current)
  247. X{
  248. X  int             nslices;
  249. X  struct descriptor_data *d;
  250. X  struct conc_list *c;
  251. X
  252. X  nslices = msec_diff(current, last) / COMMAND_TIME_MSEC;
  253. X
  254. X  if (nslices > 0)
  255. X  {
  256. X    for (c = firstc; c; c = c->next)
  257. X      for (d = c->firstd; d; d = d->next)
  258. X      {
  259. X    d->quota += COMMANDS_PER_TIME * nslices;
  260. X    if (d->quota > COMMAND_BURST_SIZE)
  261. X      d->quota = COMMAND_BURST_SIZE;
  262. X      }
  263. X  }
  264. X  return msec_add(last, nslices * COMMAND_TIME_MSEC);
  265. X}
  266. X
  267. Xint
  268. X                notify(dbref player2, const char *msg)
  269. X{
  270. X  struct descriptor_data *d;
  271. X  struct conc_list *c;
  272. X  int             retval = 0;
  273. X
  274. X#ifdef COMPRESS
  275. X  extern const char *uncompress(const char *);
  276. X
  277. X  msg = uncompress(msg);
  278. X#endif                       /* COMPRESS */
  279. X  for (c = firstc; c; c = c->next)
  280. X    for (d = c->firstd; d; d = d->next)
  281. X    {
  282. X      if (d->connected && d->player == player2)
  283. X      {
  284. X    queue_string(d, msg);
  285. X    queue_write(d, "\n", 1);
  286. X    retval++;
  287. X      }
  288. X    }
  289. X  return (retval);
  290. X}
  291. X
  292. Xint
  293. X                process_input(d, buf, got)
  294. X  struct descriptor_data *d;
  295. X  char           *buf;
  296. X  int             got;
  297. X{
  298. X  char           *p, *pend, *q, *qend;
  299. X
  300. X  d->last_time = time(0);
  301. X  if (!d->raw_input)
  302. X  {
  303. X    MALLOC(d->raw_input, char, MAX_COMMAND_LEN);
  304. X    d->raw_input_at = d->raw_input;
  305. X  }
  306. X  p = d->raw_input_at;
  307. X  pend = d->raw_input + MAX_COMMAND_LEN - 1;
  308. X  for (q = buf, qend = buf + got; q < qend; q++)
  309. X  {
  310. X    if (*q == '\n')
  311. X    {
  312. X      *p = '\0';
  313. X      if (p > d->raw_input)
  314. X    save_command(d, d->raw_input);
  315. X      p = d->raw_input;
  316. X    } else
  317. X    if (p < pend && isascii(*q) && isprint(*q))
  318. X    {
  319. X      *p++ = *q;
  320. X    }
  321. X  }
  322. X  if (p > d->raw_input)
  323. X  {
  324. X    d->raw_input_at = p;
  325. X  } else
  326. X  {
  327. X    FREE(d->raw_input);
  328. X    d->raw_input = 0;
  329. X    d->raw_input_at = 0;
  330. X  }
  331. X  return 1;
  332. X}
  333. X
  334. Xvoid            process_commands()
  335. X{
  336. X  int             nprocessed;
  337. X  struct descriptor_data *d, *dnext, *dlast;
  338. X  struct conc_list *c;
  339. X  struct text_block *t;
  340. X  char            header[4];
  341. X
  342. X  do
  343. X  {
  344. X    nprocessed = 0;
  345. X    for (c = firstc; c; c = c->next)
  346. X    {
  347. X      dlast = 0;
  348. X      for (d = c->firstd; d; d = dnext)
  349. X      {
  350. X    dnext = d->next;
  351. X    if (d->quota > 0 && (t = d->input.head))
  352. X    {
  353. X      d->quota--;
  354. X      nprocessed++;
  355. X      if (!do_command(d, t->start))
  356. X      {
  357. X        header[0] = 0;
  358. X        header[1] = 2;
  359. X        header[2] = d->num;
  360. X        queue_message(c, header, 3);
  361. X        if (dlast)
  362. X          dlast->next = dnext;
  363. X        else
  364. X          c->firstd = dnext;
  365. X        shutdownsock(d);
  366. X        FREE(d);
  367. X        break;
  368. X      } else
  369. X      {
  370. X        d->input.head = t->nxt;
  371. X        if (!d->input.head)
  372. X          d->input.tail = &d->input.head;
  373. X        free_text_block(t);
  374. X      }
  375. X    }
  376. X    dlast = d;
  377. X      }
  378. X    }
  379. X  } while (nprocessed > 0);
  380. X}
  381. X
  382. Xvoid dump_users(struct descriptor_data * e, char *user)
  383. X{
  384. X  static struct conc_list *rwclist[NOFILE];
  385. X  static struct descriptor_data *rwdlist[NOFILE];
  386. X  int             ccount, dcount, dloop, cloop;
  387. X
  388. X  struct descriptor_data *d;
  389. X  struct conc_list *c;
  390. X  long            now;
  391. X  int             counter = 0;
  392. X  static int      maxcounter = 0;
  393. X  int             wizard, reversed, tabular;
  394. X  char            buf[1024];
  395. X
  396. X
  397. X# ifdef DO_WHOCHECK
  398. X  writelog("WHO CHECK %d\n", sizeof(rwclist));
  399. X  writelog("WHO CHECK %d\n", sizeof(rwdlist));
  400. X# endif
  401. X
  402. X  while (*user && isspace(*user))
  403. X    user++;
  404. X  if (!*user)
  405. X    user = NULL;
  406. X
  407. X  reversed = e->connected && Flag(e->player, REVERSED_WHO);
  408. X  tabular = e->connected && Flag(e->player, TABULAR_WHO);
  409. X
  410. X  time(&now);
  411. X
  412. X  queue_string(e, tabular ? "Player Name          On For Idle\n" :
  413. X           "Current Players:\n");
  414. X#ifdef GOD_MODE
  415. X  wizard = e->connected && God(e->player);
  416. X#else  GOD_MODE
  417. X  wizard = e->connected && Wizard(e->player);
  418. X#endif GOD_MODE
  419. X
  420. X  if (reversed)
  421. X  {
  422. X    ccount = 0;
  423. X    for (c = firstc; c; c = c->next)
  424. X      rwclist[ccount++] = c;
  425. X    for (cloop = ccount - 1; cloop >= 0; --cloop)
  426. X    {
  427. X      dcount = 0;
  428. X      for (d = rwclist[cloop]->firstd; d; d = d->next)
  429. X    rwdlist[dcount++] = d;
  430. X      for (dloop = dcount - 1; dloop >= 0; --dloop)
  431. X      {
  432. X    d = rwdlist[dloop];
  433. X    if (d->connected &&
  434. X        ++counter && /* Count everyone connected */
  435. X        (!user || string_prefix(db[d->player].name, user)))
  436. X    {
  437. X      if (tabular)
  438. X      {
  439. X        sprintf(buf, "%-16s %10s %4s",
  440. X            db[d->player].name,
  441. X            time_format_1(now - d->connected_at),
  442. X            time_format_2(now - d->last_time));
  443. X
  444. X        if (wizard)
  445. X          sprintf(buf, "%s  %s", buf, d->hostname);
  446. X      } else
  447. X      {
  448. X        sprintf(buf, "%s idle %d seconds",
  449. X            db[d->player].name, now - d->last_time);
  450. X        if (wizard)
  451. X          sprintf(buf, "%s from host %s", buf, d->hostname);
  452. X      }
  453. X      strcat(buf, "\n");
  454. X      queue_string(e, buf);
  455. X    }
  456. X      }
  457. X    }
  458. X  } else
  459. X  {
  460. X    for (c = firstc; c; c = c->next)
  461. X    {
  462. X      for (d = c->firstd; d; d = d->next)
  463. X      {
  464. X    if (d->connected &&
  465. X        ++counter && /* Count everyone connected */
  466. X        (!user || string_prefix(db[d->player].name, user)))
  467. X    {
  468. X      if (tabular)
  469. X      {
  470. X        sprintf(buf, "%-16s %10s %4s",
  471. X            db[d->player].name,
  472. X            time_format_1(now - d->connected_at),
  473. X            time_format_2(now - d->last_time));
  474. X
  475. X        if (wizard)
  476. X          sprintf(buf, "%s  %s", buf, d->hostname);
  477. X      } else
  478. X      {
  479. X        sprintf(buf, "%s idle %d seconds",
  480. X            db[d->player].name, now - d->last_time);
  481. X        if (wizard)
  482. X          sprintf(buf, "%s from host %s", buf, d->hostname);
  483. X      }
  484. X      strcat(buf, "\n");
  485. X      queue_string(e, buf);
  486. X    }
  487. X      }
  488. X    }
  489. X  }
  490. X  
  491. X  if (counter > maxcounter)
  492. X  { maxcounter = counter;
  493. X    if (counter > 30)
  494. X    { writelog ("%d users logged in\n", counter); }
  495. X  }
  496. X  
  497. X  sprintf(buf, "%d user%s connected\n", counter,
  498. X      counter == 1 ? " is" : "s are");
  499. X  queue_string(e, buf);
  500. X}
  501. X
  502. Xvoid free_text_block(struct text_block * t)
  503. X{
  504. X                  FREE(t->buf);
  505. X  FREE((char *)t);
  506. X}
  507. X
  508. X#ifndef BOOLEXP_DEBUGGING
  509. Xvoid main(int argc, char **argv)
  510. X{
  511. X  int             pid;
  512. X
  513. X  if (argc < 3)
  514. X  {
  515. X    fprintf(stderr, "Usage: %s infile dumpfile [port iport logfile]\n", *argv);
  516. X    exit(1);
  517. X
  518. X  }
  519. X  if (argc > 3)
  520. X    port = atoi(argv[3]);
  521. X  if (argc > 4)
  522. X    intport = atoi(argv[4]);
  523. X  if (argc > 5)
  524. X    logfile = argv[5];
  525. X
  526. X  start_log();
  527. X
  528. X  if (init_game(argv[1], argv[2]) < 0)
  529. X  {
  530. X    writelog("INIT: Couldn't load %s\n", argv[1]);
  531. X    exit(2);
  532. X  }
  533. X  pid = vfork();
  534. X  if (pid < 0)
  535. X  {
  536. X    perror("fork");
  537. X    exit(-1);
  538. X  }
  539. X  if (pid == 0)
  540. X  {
  541. X    char            pstr[32], istr[32], clvl[32];
  542. X
  543. X    /* Add port argument to concentrator */
  544. X    sprintf(pstr, "%d", port);
  545. X    sprintf(istr, "%d", intport);
  546. X    sprintf(clvl, "%d", 1);
  547. X    execl("concentrate", "conc", pstr, istr, clvl, 0);
  548. X  }
  549. X  set_signals();
  550. X  start_port(port);
  551. X  main_loop();
  552. X  close_sockets();
  553. X  dump_database();
  554. X  exit(0);
  555. X}
  556. X
  557. X#endif
  558. X
  559. Xvoid start_log()
  560. X{
  561. X#ifdef DETACH
  562. X  if              (!debug)
  563. X  {
  564. X    int             i;
  565. X
  566. X    if (fork() != 0)
  567. X      exit(0);
  568. X
  569. X    i = open("/dev/tty", O_RDWR, 0);
  570. X    if (i != -1)
  571. X    {
  572. X      ioctl(i, TIOCNOTTY, 0);
  573. X      close(i);
  574. X    }
  575. X  }
  576. X  freopen(logfile, "a", stderr);
  577. X  setbuf(stderr, NULL);
  578. X#endif                       /* DETACH */
  579. X}
  580. X
  581. Xvoid set_signals(void)
  582. X{
  583. X  int             dump_status(void);
  584. X  signal(SIGPIPE, SIG_IGN);
  585. X
  586. X  signal(SIGINT, (void *)sigshutdown);
  587. X  signal(SIGTERM, (void *)sigshutdown);
  588. X
  589. X#ifdef DETACH
  590. X  signal(SIGUSR2, (void *)logsynch);
  591. X#else                       /* DETACH */
  592. X  signal(SIGUSR2, (void *)bailout);
  593. X#endif                       /* DETACH */
  594. X
  595. X  if (debug)
  596. X    return;
  597. X
  598. X# ifdef NOCOREDUMP
  599. X  signal(SIGQUIT, (void *)bailout);
  600. X  signal(SIGILL, (void *)bailout);
  601. X  signal(SIGTRAP, (void *)bailout);
  602. X  signal(SIGIOT, (void *)bailout);
  603. X  signal(SIGEMT, (void *)bailout);
  604. X  signal(SIGFPE, (void *)bailout);
  605. X  signal(SIGBUS, (void *)bailout);
  606. X  signal(SIGSEGV, (void *)bailout);
  607. X  signal(SIGSYS, (void *)bailout);
  608. X  signal(SIGTERM, (void *)bailout);
  609. X  signal(SIGXCPU, (void *)bailout);
  610. X  signal(SIGXFSZ, (void *)bailout);
  611. X  signal(SIGVTALRM, (void *)bailout);
  612. X# endif
  613. X}
  614. X
  615. Xint
  616. X                msec_diff(struct timeval now, struct timeval then)
  617. X{
  618. X                  return ((now.tv_sec - then.tv_sec) * 1000
  619. X               +               (now.tv_usec - then.tv_usec) / 1000);
  620. X}
  621. X
  622. Xvoid
  623. X                clearstrings(struct descriptor_data * d)
  624. X{
  625. X  if              (d->output_prefix)
  626. X  {
  627. X                    FREE(d->output_prefix);
  628. X    d->output_prefix = 0;
  629. X  }
  630. X  if (d->output_suffix)
  631. X  {
  632. X    FREE(d->output_suffix);
  633. X    d->output_suffix = 0;
  634. X  }
  635. X}
  636. X
  637. Xvoid
  638. X                shutdownsock(struct descriptor_data * d)
  639. X{
  640. X  if              (d->connected)
  641. X  {
  642. X                    writelog("DISCONNECT descriptor %d,%d player %s(%d)\n", d->descriptor, d->num, db[d->player].name, d->player);
  643. X#ifdef CONNECT_MESSAGES
  644. X    announce_disconnect(d->player);
  645. X#endif                       /* CONNECT_MESSAGES */
  646. X  } else
  647. X  {
  648. X    writelog("DISCONNECT descriptor %d,%d never connected\n", d->descriptor, d->num);
  649. X  }
  650. X  clearstrings(d);
  651. X  freeqs(d);
  652. X}
  653. X
  654. Xstruct descriptor_data *
  655. X                initializesock(struct sockaddr_in * a)
  656. X{
  657. X  struct descriptor_data *d;
  658. X
  659. X  MALLOC(d, struct descriptor_data, 1);
  660. X  d->connected = 0;
  661. X  d->output_prefix = 0;
  662. X  d->output_suffix = 0;
  663. X  d->output_size = 0;
  664. X  d->output.head = 0;
  665. X  d->output.tail = &d->output.head;
  666. X  d->input.head = 0;
  667. X  d->input.tail = &d->input.head;
  668. X  d->raw_input = 0;
  669. X  d->raw_input_at = 0;
  670. X  d->quota = COMMAND_BURST_SIZE;
  671. X  d->last_time = 0;
  672. X  d->address = *a;               /* This will be the address of the
  673. X                        * concentrator */
  674. X  d->hostname = "";               /* This will be set during connect */
  675. X
  676. X  welcome_user(d);
  677. X  return d;
  678. X}
  679. X
  680. Xstruct text_block *
  681. X                make_text_block(const char *s, int n)
  682. X{
  683. X  struct text_block *p;
  684. X
  685. X  MALLOC(p, struct text_block, 1);
  686. X  MALLOC(p->buf, char, n);
  687. X  bcopy(s, p->buf, n);
  688. X  p->nchars = n;
  689. X  p->start = p->buf;
  690. X  p->nxt = 0;
  691. X  return p;
  692. X}
  693. X
  694. Xvoid
  695. X                add_to_queue(struct text_queue * q, const char *b, int n)
  696. X{
  697. X  struct text_block *p;
  698. X
  699. X  if (n == 0)
  700. X    return;
  701. X
  702. X  p = make_text_block(b, n);
  703. X  p->nxt = 0;
  704. X  *q->tail = p;
  705. X  q->tail = &p->nxt;
  706. X}
  707. X
  708. Xint
  709. X                flush_queue(struct text_queue * q, int n)
  710. X{
  711. X  struct text_block *p;
  712. X  int             really_flushed = 0;
  713. X
  714. X  n += strlen(flushed_message);
  715. X
  716. X  while (n > 0 && (p = q->head))
  717. X  {
  718. X    n -= p->nchars;
  719. X    really_flushed += p->nchars;
  720. X    q->head = p->nxt;
  721. X    free_text_block(p);
  722. X  }
  723. X  p = make_text_block(flushed_message, strlen(flushed_message));
  724. X  p->nxt = q->head;
  725. X  q->head = p;
  726. X  if (!p->nxt)
  727. X    q->tail = &p->nxt;
  728. X  really_flushed -= p->nchars;
  729. X  return really_flushed;
  730. X}
  731. X
  732. Xint
  733. X                queue_write(struct descriptor_data * d, const char *b, int n)
  734. X{
  735. X  int             space;
  736. X
  737. X  space = MAX_OUTPUT - d->output_size - n;
  738. X  if (space < 0)
  739. X    d->output_size -= flush_queue(&d->output, -space);
  740. X  add_to_queue(&d->output, b, n);
  741. X  d->output_size += n;
  742. X  return n;
  743. X}
  744. X
  745. Xint
  746. X                queue_string(struct descriptor_data * d, const char *s)
  747. X{
  748. X                  return queue_write(d, s, strlen(s));
  749. X}
  750. X
  751. Xvoid
  752. X                freeqs(struct descriptor_data * d)
  753. X{
  754. X  struct text_block *cur, *next;
  755. X
  756. X  cur = d->output.head;
  757. X  while (cur)
  758. X  {
  759. X    next = cur->nxt;
  760. X    free_text_block(cur);
  761. X    cur = next;
  762. X  }
  763. X  d->output.head = 0;
  764. X  d->output.tail = &d->output.head;
  765. X
  766. X  cur = d->input.head;
  767. X  while (cur)
  768. X  {
  769. X    next = cur->nxt;
  770. X    free_text_block(cur);
  771. X    cur = next;
  772. X  }
  773. X  d->input.head = 0;
  774. X  d->input.tail = &d->input.head;
  775. X
  776. X  if (d->raw_input)
  777. X    FREE(d->raw_input);
  778. X  d->raw_input = 0;
  779. X  d->raw_input_at = 0;
  780. X}
  781. X
  782. Xvoid
  783. X                welcome_user(struct descriptor_data * d)
  784. X{
  785. X  queue_string(d, WELCOME_MESSAGE);
  786. X  file_date(d, NEWS_FILE);
  787. X# ifdef CONNECT_FILE
  788. X  do_connect_msg(d, CONNECT_FILE);
  789. X# endif
  790. X}
  791. X
  792. Xvoid
  793. X                goodbye_user(struct descriptor_data * d)
  794. X{
  795. X                  queue_string(d, LEAVE_MESSAGE);
  796. X}
  797. X
  798. Xchar           *
  799. X                strsave(const char *s)
  800. X{
  801. X  char           *p;
  802. X
  803. X  MALLOC(p, char, strlen(s) + 1);
  804. X
  805. X  if (p)
  806. X    strcpy(p, s);
  807. X  return p;
  808. X}
  809. X
  810. Xvoid
  811. X                save_command(struct descriptor_data * d, const char *command)
  812. X{
  813. X                  add_to_queue(&d->input, command, strlen(command) + 1);
  814. X}
  815. X
  816. Xvoid
  817. X                set_userstring(char **userstring, const char *command)
  818. X{
  819. X  if              (*userstring)
  820. X  {
  821. X                    FREE(*userstring);
  822. X    *userstring = 0;
  823. X  }
  824. X  while (*command && isascii(*command) && isspace(*command))
  825. X    command++;
  826. X  if (*command)
  827. X    *userstring = strsave(command);
  828. X}
  829. X
  830. Xint
  831. X                do_command(struct descriptor_data * d, char *command)
  832. X{
  833. X  if              (!strcmp(command, QUIT_COMMAND))
  834. X  {
  835. X                    goodbye_user(d);
  836. X    return 0;
  837. X  } else
  838. X  if (!strncmp(command, WHO_COMMAND, strlen(WHO_COMMAND)))
  839. X  {
  840. X    if (d->output_prefix)
  841. X    {
  842. X      queue_string(d, d->output_prefix);
  843. X      queue_write(d, "\n", 1);
  844. X    }
  845. X    dump_users(d, command + strlen(WHO_COMMAND));
  846. X    if (d->output_suffix)
  847. X    {
  848. X      queue_string(d, d->output_suffix);
  849. X      queue_write(d, "\n", 1);
  850. X    }
  851. X  } else
  852. X    if (d->connected &&
  853. X    !strncmp(command, PREFIX_COMMAND, strlen(PREFIX_COMMAND)))
  854. X  {
  855. X#ifdef ROBOT_MODE
  856. X    if (!Robot(d->player))
  857. X    {
  858. X#ifndef TINKER
  859. X      notify(d->player,
  860. X         "Only robots can use OUTPUTPREFIX; contact a Wizard.");
  861. X#else TINKER
  862. X      notify(d->player,
  863. X         "Only robots can use OUTPUTPREFIX; contact a Tinker.");
  864. X#endif TINKER
  865. X      return 1;
  866. X    }
  867. X    if (!d->connected)
  868. X      return 1;
  869. X#endif ROBOT_MODE
  870. X    set_userstring(&d->output_prefix, command + strlen(PREFIX_COMMAND));
  871. X  } else
  872. X    if (d->connected &&
  873. X    !strncmp(command, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND)))
  874. X  {
  875. X#ifdef ROBOT_MODE
  876. X    if (!Robot(d->player))
  877. X    {
  878. X#ifndef TINKER
  879. X      notify(d->player,
  880. X         "Only robots can use OUTPUTSUFFIX; contact a Wizard.");
  881. X#else TINKER
  882. X      notify(d->player,
  883. X         "Only robots can use OUTPUTSUFFIX; contact a Tinker.");
  884. X#endif TINKER
  885. X      return 1;
  886. X    }
  887. X#endif ROBOT_MODE
  888. X    set_userstring(&d->output_suffix, command + strlen(SUFFIX_COMMAND));
  889. X  } else
  890. X  {
  891. X    if (d->connected)
  892. X    {
  893. X      if (d->output_prefix)
  894. X      {
  895. X    queue_string(d, d->output_prefix);
  896. X    queue_write(d, "\n", 1);
  897. X      }
  898. X      process_command(d->player, command);
  899. X      if (d->output_suffix)
  900. X      {
  901. X    queue_string(d, d->output_suffix);
  902. X    queue_write(d, "\n", 1);
  903. X      }
  904. X    } else
  905. X    {
  906. X      check_connect(d, command);
  907. X    }
  908. X  }
  909. X  return 1;
  910. X}
  911. X
  912. Xvoid
  913. X                check_connect(struct descriptor_data * d, const char *msg)
  914. X{
  915. X  char            command[MAX_COMMAND_LEN];
  916. X  char            user[MAX_COMMAND_LEN];
  917. X  char            password[MAX_COMMAND_LEN];
  918. X  dbref           player;
  919. X
  920. X  parse_connect(msg, command, user, password);
  921. X
  922. X  if (!strncmp(command, "co", 2))
  923. X  {
  924. X    player = connect_player(user, password);
  925. X    if (player == NOTHING)
  926. X    {
  927. X      queue_string(d, connect_fail);
  928. X      writelog("FAILED CONNECT %s on descriptor %d,%d\n", user, d->descriptor, d->num);
  929. X    } else
  930. X    {
  931. X      writelog("CONNECTED %s(%d) on descriptor %d,%d %s\n",
  932. X           db[player].name, player, d->descriptor, d->num, d->hostname);
  933. X      d->connected = 1;
  934. X      d->connected_at = time(NULL);
  935. X      d->player = player;
  936. X      do_motd(player);
  937. X      do_look_around(player);
  938. X#ifdef CONNECT_MESSAGES
  939. X      announce_connect(player);
  940. X#endif                       /* CONNECT_MESSAGES */
  941. X    }
  942. X  } else
  943. X  if (!strncmp(command, "cr", 2))
  944. X  {
  945. X#ifndef REGISTRATION
  946. X    player = create_player(user, password);
  947. X    if (player == NOTHING)
  948. X    {
  949. X      queue_string(d, create_fail);
  950. X      writelog("FAILED CREATE %s on descriptor %d,%d %s\n",
  951. X           user, d->descriptor, d->num, d->hostname);
  952. X    } else
  953. X    {
  954. X      writelog("CREATED %s(%d) on descriptor %d,%d %s\n",
  955. X           db[player].name, player, d->descriptor, d->num, d->hostname);
  956. X      d->connected = 1;
  957. X      d->connected_at = time(0);
  958. X      d->player = player;
  959. X      do_motd(player);
  960. X      do_look_around(player);
  961. X#ifdef CONNECT_MESSAGES
  962. X      announce_connect(player);
  963. X#endif                       /* CONNECT_MESSAGES */
  964. X    }
  965. X#else
  966. X    queue_string(d, REGISTER_MESSAGE);
  967. X#endif                       /* REGISTRATION */
  968. X  } else
  969. X  {
  970. X    welcome_user(d);
  971. X  }
  972. X}
  973. X
  974. Xvoid
  975. X                parse_connect(const char *msg, char *command, char *user, char *pass)
  976. X{
  977. X  char           *p;
  978. X
  979. X  while (*msg && isascii(*msg) && isspace(*msg))
  980. X    msg++;
  981. X  p = command;
  982. X  while (*msg && isascii(*msg) && !isspace(*msg))
  983. X    *p++ = *msg++;
  984. X  *p = '\0';
  985. X  while (*msg && isascii(*msg) && isspace(*msg))
  986. X    msg++;
  987. X  p = user;
  988. X  while (*msg && isascii(*msg) && !isspace(*msg))
  989. X    *p++ = *msg++;
  990. X  *p = '\0';
  991. X  while (*msg && isascii(*msg) && isspace(*msg))
  992. X    msg++;
  993. X  p = pass;
  994. X  while (*msg && isascii(*msg) && !isspace(*msg))
  995. X    *p++ = *msg++;
  996. X  *p = '\0';
  997. X}
  998. X
  999. Xvoid
  1000. X                close_sockets(void)
  1001. X{
  1002. X  struct descriptor_data *d, *dnext;
  1003. X  struct conc_list *c;
  1004. X  char            header[4];
  1005. X
  1006. X  for (c = firstc; c; c = c->next)
  1007. X  {
  1008. X    /* conc.c now handles printing the Going Down - Bye message */
  1009. X    shutdown(c->sock, 0);
  1010. X    close(c->sock);
  1011. X  }
  1012. X  close(sock);
  1013. X}
  1014. X
  1015. Xvoid
  1016. X                emergency_shutdown(void)
  1017. X{
  1018. X                  close_sockets();
  1019. X}
  1020. X
  1021. Xint
  1022. X                bailout(int sig, int code, struct sigcontext * scp)
  1023. X{
  1024. X  long           *ptr;
  1025. X  int             i;
  1026. X
  1027. X  writelog("BAILOUT: caught signal %d code %d", sig, code);
  1028. X  ptr = (long *)scp;
  1029. X  for (i = 0; i < sizeof(struct sigcontext); i++)
  1030. X    writelog("  %08lx\n", *ptr);
  1031. X  panic("PANIC on spurious signal");
  1032. X  _exit(7);
  1033. X  return 0;
  1034. X}
  1035. X
  1036. Xchar           *
  1037. X                time_format_1(long dt)
  1038. X{
  1039. X  register struct tm *delta;
  1040. X  static char     buf[64];
  1041. X
  1042. X  delta = gmtime(&dt);
  1043. X  if (delta->tm_yday > 0)
  1044. X  {
  1045. X    sprintf(buf, "%dd %02d:%02d",
  1046. X        delta->tm_yday, delta->tm_hour, delta->tm_min);
  1047. X  } else
  1048. X  {
  1049. X    sprintf(buf, "%02d:%02d",
  1050. X        delta->tm_hour, delta->tm_min);
  1051. X  }
  1052. X  return buf;
  1053. X}
  1054. X
  1055. Xchar           *
  1056. X                time_format_2(long dt)
  1057. X{
  1058. X  register struct tm *delta;
  1059. X  static char     buf[64];
  1060. X
  1061. X  delta = gmtime(&dt);
  1062. X  if (delta->tm_yday > 0)
  1063. X  {
  1064. X    sprintf(buf, "%dd", delta->tm_yday);
  1065. X  } else
  1066. X  if (delta->tm_hour > 0)
  1067. X  {
  1068. X    sprintf(buf, "%dh", delta->tm_hour);
  1069. X  } else
  1070. X  if (delta->tm_min > 0)
  1071. X  {
  1072. X    sprintf(buf, "%dm", delta->tm_min);
  1073. X  } else
  1074. X  {
  1075. X    sprintf(buf, "%ds", delta->tm_sec);
  1076. X  }
  1077. X  return buf;
  1078. X}
  1079. X
  1080. X#ifdef CONNECT_MESSAGES
  1081. Xvoid
  1082. X                announce_connect(dbref player)
  1083. X{
  1084. X  dbref           loc;
  1085. X  char            buf[BUFFER_LEN];
  1086. X
  1087. X  if ((loc = getloc(player)) == NOTHING)
  1088. X    return;
  1089. X  if (Dark(player) || Dark(loc))
  1090. X    return;
  1091. X
  1092. X  sprintf(buf, "%s has connected.", db[player].name);
  1093. X
  1094. X  notify_except(db[loc].contents, player, buf);
  1095. X}
  1096. X
  1097. Xvoid
  1098. X                announce_disconnect(dbref player)
  1099. X{
  1100. X  dbref           loc;
  1101. X  char            buf[BUFFER_LEN];
  1102. X
  1103. X  if ((loc = getloc(player)) == NOTHING)
  1104. X    return;
  1105. X  if (Dark(player) || Dark(loc))
  1106. X    return;
  1107. X
  1108. X  sprintf(buf, "%s has disconnected.", db[player].name);
  1109. X
  1110. X  notify_except(db[loc].contents, player, buf);
  1111. X}
  1112. X
  1113. X#endif                       /* CONNECT_MESSAGES */
  1114. X
  1115. Xint
  1116. X                sigshutdown(int sig, int code, struct sigcontext * scp)
  1117. X{
  1118. X                  writelog("SHUTDOWN: on signal %d code %d\n", sig, code);
  1119. X  shutdown_flag = 1;
  1120. X  return 0;
  1121. X}
  1122. X
  1123. X#ifdef DETACH
  1124. Xint
  1125. X                logsynch()
  1126. X{
  1127. X                  freopen(logfile, "a", stderr);
  1128. X  setbuf(stderr, NULL);
  1129. X  writelog("log file reopened\n");
  1130. X  return 0;
  1131. X}
  1132. X
  1133. X#endif                       /* DETACH */
  1134. X
  1135. X#include <sys/stat.h>
  1136. X
  1137. Xvoid
  1138. X                file_date(struct descriptor_data * d, char *file)
  1139. X{
  1140. X  static char     buf[80];
  1141. X  extern char    *ctime(long *clock);
  1142. X  struct stat     statb;
  1143. X  char           *tstring;
  1144. X  char           *cp;
  1145. X
  1146. X  if (stat(file, &statb) == -1)
  1147. X    return;
  1148. X
  1149. X  tstring = ctime(&statb.st_mtime);
  1150. X  if ((cp = (char *)index(tstring, '\n')) != NULL)
  1151. X    *cp = '\0';
  1152. X
  1153. X  strcpy(buf, "News last updated ");
  1154. X  strcat(buf, tstring);
  1155. X  strcat(buf, "\n\n");
  1156. X
  1157. X  queue_string(d, (char *)buf);
  1158. X}
  1159. X
  1160. Xvoid            main_loop()
  1161. X{
  1162. X  struct message *ptr;
  1163. X  int             found, newsock, lastsock, len, loop;
  1164. X  int             accepting;
  1165. X  struct timeval  tv;
  1166. X  struct sockaddr_in sin;
  1167. X  fd_set          in, out;
  1168. X  char            data[1025], *p1, *p2, buffer[1025], header[4];
  1169. X  struct conc_list *c, *tempc, *nextc, *lastc;
  1170. X  struct descriptor_data *d, *tempd, *nextd;
  1171. X  struct timeval  last_slice, current_time;
  1172. X  struct timeval  next_slice;
  1173. X  struct timeval  slice_timeout;
  1174. X  short           templen;
  1175. X
  1176. X  accepting = 1;
  1177. X  lastsock = sock + 1;
  1178. X  while (!shutdown_flag)
  1179. X  {
  1180. X    gettimeofday(¤t_time, (struct timezone *) 0);
  1181. X    last_slice = update_quotas(last_slice, current_time);
  1182. X
  1183. X    process_commands();
  1184. X
  1185. X    if (shutdown_flag)
  1186. X      break;
  1187. X
  1188. X    next_slice = msec_add(last_slice, COMMAND_TIME_MSEC);
  1189. X    slice_timeout = timeval_sub(next_slice, current_time);
  1190. X
  1191. X    FD_ZERO(&in);
  1192. X    FD_ZERO(&out);
  1193. X
  1194. X    FD_SET(sock, &in);
  1195. X    for (c = firstc; c; c = c->next)
  1196. X      process_output(c);
  1197. X    for (c = firstc; c; c = c->next)
  1198. X      if (c->sock)
  1199. X      {
  1200. X    if (c->ilen < BUFSIZE)
  1201. X      FD_SET(c->sock, &in);
  1202. X    len = c->first ? c->first->len : 0;
  1203. X    while (c->first && ((c->olen + len + 2) < BUFSIZE))
  1204. X    {
  1205. X      templen = c->first->len;
  1206. X      bcopy(&templen, c->outgoing + c->olen, 2);
  1207. X      bcopy(c->first->data, c->outgoing + c->olen + 2, len);
  1208. X      c->olen += len + 2;
  1209. X      ptr = c->first;
  1210. X      c->first = ptr->next;
  1211. X      FREE(ptr->data);
  1212. X      FREE(ptr);
  1213. X      if (c->last == ptr)
  1214. X        c->last = 0;
  1215. X      len = c->first ? c->first->len : 0;
  1216. X    }
  1217. X    if (c->olen)
  1218. X      FD_SET(c->sock, &out);
  1219. X      }
  1220. X    tv.tv_sec = 1000;
  1221. X    tv.tv_usec = 0;
  1222. X
  1223. X    found = select(lastsock, &in, &out, (fd_set *) 0, &tv);
  1224. X    if (found < 0)
  1225. X      continue;
  1226. X    if (accepting && FD_ISSET(sock, &in))
  1227. X    {
  1228. X      len = sizeof(sin);
  1229. X      newsock = accept(sock, (struct sockaddr *) & sin, &len);
  1230. X      if (newsock >= 0)
  1231. X      {
  1232. X    if (newsock >= lastsock)
  1233. X      lastsock = newsock + 1;
  1234. X    if (fcntl(newsock, F_SETFL, FNDELAY) == -1)
  1235. X    {
  1236. X      perror("make_nonblocking: fcntl");
  1237. X    }
  1238. X    MALLOC(tempc, struct conc_list, 1);
  1239. X    tempc->next = firstc;
  1240. X    tempc->firstd = 0;
  1241. X    tempc->first = 0;
  1242. X    tempc->last = 0;
  1243. X    tempc->status = 0;
  1244. X    /* Imcomming and outgoing I/O buffers */
  1245. X    MALLOC(tempc->incoming, char, BUFSIZE);
  1246. X    tempc->ilen = 0;
  1247. X    MALLOC(tempc->outgoing, char, BUFSIZE);
  1248. X    tempc->olen = 0;
  1249. X    firstc = tempc;
  1250. X    firstc->sock = newsock;
  1251. X    writelog("CONCENTRATOR CONNECT: sock %d, addr %x\n", newsock, sin.sin_addr.s_addr);
  1252. X      }
  1253. X    }
  1254. X    for (c = firstc; c; c = nextc)
  1255. X    {
  1256. X      nextc = c->next;
  1257. X#ifdef CHECKC
  1258. X      if (!(c->sock))
  1259. X    writelog("CONSISTENCY CHECK: Concentrator found with null socket #\n");
  1260. X#endif
  1261. X      if ((FD_ISSET(c->sock, &in)) && (c->ilen < BUFSIZE))
  1262. X      {
  1263. X    int             i;
  1264. X    len = recv(c->sock, c->incoming + c->ilen,
  1265. X           BUFSIZE - c->ilen, 0);
  1266. X    if (len == 0)
  1267. X    {
  1268. X      struct message *mptr, *tempm;
  1269. X      writelog("CONCENTRATOR DISCONNECT: %d\n", c->sock);
  1270. X      close(c->sock);
  1271. X      d = c->firstd;
  1272. X      while (d)
  1273. X      {
  1274. X        shutdownsock(d);
  1275. X        tempd = d;
  1276. X        d = d->next;
  1277. X        FREE(tempd);
  1278. X      }
  1279. X      if (firstc == c)
  1280. X        firstc = firstc->next;
  1281. X      else
  1282. X        lastc->next = c->next;
  1283. X      FREE(c->incoming);
  1284. X      FREE(c->outgoing);
  1285. X      mptr = c->first;
  1286. X      while (mptr)
  1287. X      {
  1288. X        tempm = mptr;
  1289. X        mptr = mptr->next;
  1290. X        FREE(mptr->data);
  1291. X        FREE(mptr);
  1292. X      }
  1293. X      FREE(c);
  1294. X      break;
  1295. X    } else
  1296. X    if (len < 0)
  1297. X    {
  1298. X      writelog("recv: %s\n", strerror(errno));
  1299. X    } else
  1300. X    {
  1301. X      int             num;
  1302. X
  1303. X      c->ilen += len;
  1304. X      while (c->ilen > 2)
  1305. X      {
  1306. X        bcopy(c->incoming, &templen, 2);
  1307. X#ifdef CHECKC
  1308. X        if (templen < 1)
  1309. X          writelog("CONSISTENCY CHECK: Message recived with lenght < 1\n");
  1310. X#endif
  1311. X        if (c->ilen >= (templen + 2))
  1312. X        {
  1313. X          num = *(c->incoming + 2);
  1314. X          /* Is it coming from the command user #? */
  1315. X          if (num == 0)
  1316. X          {
  1317. X        /* Proccess commands */
  1318. X        switch (*(c->incoming + 3))
  1319. X        {
  1320. X        case 1:           /* connect */
  1321. X          d = initializesock(&sin);
  1322. X          d->descriptor = c->sock;
  1323. X          d->next = c->firstd;
  1324. X          c->firstd = d;
  1325. X          d->num = *(c->incoming + 4);
  1326. X          MALLOC(d->hostname, char,
  1327. X             templen - 5);
  1328. X          bcopy(c->incoming + 9, d->hostname,
  1329. X            templen - 6);
  1330. X          *(d->hostname + templen - 7) = 0;
  1331. X#ifdef DEBUG
  1332. X          writelog("USER CONNECT %d,%d from host %s\n", c->sock, d->num, d->hostname);
  1333. X#endif
  1334. X          break;
  1335. X        case 2:           /* disconnect */
  1336. X          tempd = 0;
  1337. X          d = c->firstd;
  1338. X          num = *(c->incoming + 4);
  1339. X          while (d)
  1340. X          {
  1341. X            if (d->num == num)
  1342. X            {
  1343. X              writelog("USER ABORTED CONNECTION %d,%d\n", c->sock, d->num);
  1344. X              shutdownsock(d);
  1345. X              if (c->firstd == d)
  1346. X            c->firstd = d->next;
  1347. X              else
  1348. X            tempd->next = d->next;
  1349. X              FREE(d);
  1350. X              break;
  1351. X            }
  1352. X            tempd = d;
  1353. X            d = d->next;
  1354. X          }
  1355. X#ifdef CHECKC
  1356. X          if (!d)
  1357. X            writelog("CONSISTENCY CHECK: Disconnect Received for unknown user %d,%d\n", c->sock, num);
  1358. X#endif
  1359. X          break;
  1360. X
  1361. X          /*
  1362. X           * This take a message from a concentrator, and logs it in
  1363. X           * the log file 
  1364. X           */
  1365. X        case 4:
  1366. X          {
  1367. X            char            buffer[2048];
  1368. X            bcopy(c->incoming + 4, buffer,
  1369. X              templen - 2);
  1370. X            *(buffer + templen - 1) = 0;
  1371. X            writelog(buffer);
  1372. X            break;
  1373. X          }
  1374. X#ifdef CHECKC
  1375. X        default:
  1376. X          writelog("CONSISTENCY CHECK: Received unknown command from concentrator\n");
  1377. X#endif
  1378. X        }
  1379. X          } else
  1380. X          {
  1381. X        d = c->firstd;
  1382. X        while (d)
  1383. X        {
  1384. X          if (d->num == num)
  1385. X          {
  1386. X            process_input(d, c->incoming + 3,
  1387. X                  templen - 1);
  1388. X            break;
  1389. X          }
  1390. X          d = d->next;
  1391. X        }
  1392. X#ifdef CHECKC
  1393. X        if (!d)
  1394. X          writelog("CONSISTENCY CHECK: Message received for unknown user %d,%d\n", c->sock, num);
  1395. X#endif
  1396. X          }
  1397. X          bcopy(c->incoming + templen + 2, c->incoming,
  1398. X            (c->ilen - templen - 2));
  1399. X          c->ilen = c->ilen - templen - 2;
  1400. X        } else
  1401. X          break;
  1402. X      }
  1403. X    }
  1404. X      }
  1405. X      lastc = c;
  1406. X    }
  1407. X    /* Send data loop */
  1408. X    for (c = firstc; c; c = c->next)
  1409. X    {
  1410. X      if (FD_ISSET(c->sock, &out))
  1411. X      {
  1412. X    if (c->olen)
  1413. X    {
  1414. X      len = send(c->sock, c->outgoing, c->olen, 0);
  1415. X      if (len > 0)
  1416. X      {
  1417. X        c->olen -= len;
  1418. X        bcopy(c->outgoing + len, c->outgoing, c->olen);
  1419. X      }
  1420. X    }
  1421. X      }
  1422. X    }
  1423. X  }
  1424. X}
  1425. X
  1426. Xvoid            process_output(struct conc_list * c)
  1427. X{
  1428. X  struct descriptor_data *d;
  1429. X  struct text_block **qp, *cur;
  1430. X  short           templen;
  1431. X
  1432. X  for (d = c->firstd; d; d = d->next)
  1433. X  {
  1434. X    qp = &d->output.head;
  1435. X    cur = *qp;
  1436. X    if (cur)
  1437. X    {
  1438. X      if (cur->nchars < 512)
  1439. X      {
  1440. X    if ((c->olen + cur->nchars + 3) < BUFSIZE)
  1441. X    {
  1442. X      templen = cur->nchars + 1;
  1443. X      bcopy(&templen, c->outgoing + c->olen, 2);
  1444. X      *(c->outgoing + c->olen + 2) = d->num;
  1445. X      strncpy(c->outgoing + c->olen + 3, cur->start, cur->nchars);
  1446. X      d->output_size -= cur->nchars;
  1447. X      c->olen += cur->nchars + 3;
  1448. X      if (!cur->nxt)
  1449. X        d->output.tail = qp;
  1450. X      *qp = cur->nxt;
  1451. X      free_text_block(cur);
  1452. X    }
  1453. X      } else
  1454. X      {
  1455. X    if ((c->olen + 512 + 3) < BUFSIZE)
  1456. X    {
  1457. X      templen = 512 + 1;
  1458. X      bcopy(&templen, c->outgoing + c->olen, 2);
  1459. X      *(c->outgoing + c->olen + 2) = d->num;
  1460. X      strncpy(c->outgoing + c->olen + 3, cur->start, 512);
  1461. X      d->output_size -= 512;
  1462. X      c->olen += 512 + 3;
  1463. X      cur->nchars -= 512;
  1464. X      cur->start += 512;
  1465. X    }
  1466. X      }
  1467. X    }
  1468. X  }
  1469. X}
  1470. X
  1471. Xvoid            boot_off(dbref player)
  1472. X{
  1473. X  struct conc_list *c;
  1474. X  struct descriptor_data *d, *lastd;
  1475. X  char            header[4];
  1476. X
  1477. X  for (c = firstc; c; c = c->next)
  1478. X  {
  1479. X    lastd = 0;
  1480. X    for (d = c->firstd; d; d = d->next)
  1481. X    {
  1482. X      if (d->connected && d->player == player)
  1483. X      {
  1484. X    header[0] = 0;
  1485. X    header[1] = 2;
  1486. X    header[2] = d->num;
  1487. X    queue_message(c, header, 3);
  1488. X    process_output(c);
  1489. X    if (lastd)
  1490. X      lastd->next = d->next;
  1491. X    else
  1492. X      c->firstd = d->next;
  1493. X    shutdownsock(d);
  1494. X    FREE(d);
  1495. X    return;
  1496. X      }
  1497. X      lastd = d;
  1498. X    }
  1499. X  }
  1500. X}
  1501. X
  1502. Xvoid            queue_message(struct conc_list * c, char *data, int len)
  1503. X{
  1504. X  struct message *ptr;
  1505. X
  1506. X  MALLOC(ptr, struct message, 1);
  1507. X  MALLOC(ptr->data, char, len);
  1508. X  ptr->len = len;
  1509. X  bcopy(data, ptr->data, len);
  1510. X  ptr->next = 0;
  1511. X  if (c->last == 0)
  1512. X    c->first = ptr;
  1513. X  else
  1514. X    c->last->next = ptr;
  1515. X  c->last = ptr;
  1516. X}
  1517. X
  1518. Xint do_connect_msg(struct descriptor_data * d, const char *filename)
  1519. X{
  1520. X  FILE           *f;
  1521. X  char            buf[BUFFER_LEN];
  1522. X  char           *p;
  1523. X
  1524. X  if ((f = fopen(filename, "r")) == NULL)
  1525. X  {
  1526. X    return (0);
  1527. X  } else
  1528. X  {
  1529. X    while (fgets(buf, sizeof buf, f))
  1530. X    {
  1531. X      queue_string(d, (char *)buf);
  1532. X
  1533. X    }
  1534. X    fclose(f);
  1535. X    return (1);
  1536. X  }
  1537. X}
  1538. END_OF_FILE
  1539. if test 33958 -ne `wc -c <'interface.c'`; then
  1540.     echo shar: \"'interface.c'\" unpacked with wrong size!
  1541. fi
  1542. # end of 'interface.c'
  1543. fi
  1544. if test -f 'joinspl.sh' -a "${1}" != "-c" ; then 
  1545.   echo shar: Will not clobber existing file \"'joinspl.sh'\"
  1546. else
  1547. echo shar: Extracting \"'joinspl.sh'\" \(333 characters\)
  1548. sed "s/^X//" >'joinspl.sh' <<'END_OF_FILE'
  1549. X#! /bin/sh
  1550. X#
  1551. X# join split lines in the config.h and small.db files
  1552. X#
  1553. Xecho creating config.h
  1554. Xsed -f comb.sed config_h.spl >config.h
  1555. Xecho creating small.db
  1556. Xsed -f comb.sed smalldb.spl >small.db
  1557. Xrm config_h.spl smalldb.spl
  1558. X#
  1559. X# build tinymud.ps from its three parts
  1560. X#
  1561. Xcreating tinymud.ps
  1562. Xcat tinymud.ps.xa? >tinymud.ps
  1563. Xrm tinymud.ps.xa?
  1564. END_OF_FILE
  1565. if test 333 -ne `wc -c <'joinspl.sh'`; then
  1566.     echo shar: \"'joinspl.sh'\" unpacked with wrong size!
  1567. fi
  1568. chmod +x 'joinspl.sh'
  1569. # end of 'joinspl.sh'
  1570. fi
  1571. if test -f 'wiz.c' -a "${1}" != "-c" ; then 
  1572.   echo shar: Will not clobber existing file \"'wiz.c'\"
  1573. else
  1574. echo shar: Extracting \"'wiz.c'\" \(16849 characters\)
  1575. sed "s/^X//" >'wiz.c' <<'END_OF_FILE'
  1576. X#include "copyright.h"
  1577. X
  1578. X/* Wizard-only commands */
  1579. X
  1580. X
  1581. X#include "db.h"
  1582. X#include "config.h"
  1583. X#include "interface.h"
  1584. X#include "match.h"
  1585. X#include "externs.h"
  1586. X
  1587. Xvoid do_teleport(dbref player, const char *arg1, const char *arg2)
  1588. X{
  1589. X    dbref victim;
  1590. X    dbref destination;
  1591. X    const char *to;
  1592. X
  1593. X#ifdef RESTRICTED_TELEPORT
  1594. X    if(!Wizard(player)) {
  1595. X#ifndef TINKER
  1596. X    notify(player, "Only a Wizard may teleport at will.");
  1597. X#else TINKER
  1598. X    notify(player, "Only a Tinker may teleport at will.");
  1599. X#endif TINKER
  1600. X    return;
  1601. X    }
  1602. X#endif /* RESTRICTED_TELEPORT */
  1603. X
  1604. X    /* get victim, destination */
  1605. X    if(*arg2 == '\0') {
  1606. X    victim = player;
  1607. X    to = arg1;
  1608. X    } else {
  1609. X    init_match(player, arg1, NOTYPE);
  1610. X    match_neighbor();
  1611. X    match_possession();
  1612. X    match_me();
  1613. X    match_absolute();
  1614. X    match_player();
  1615. X
  1616. X    if((victim = noisy_match_result()) == NOTHING) {
  1617. X        return;
  1618. X    }
  1619. X    to = arg2;
  1620. X    }
  1621. X
  1622. X    /* get destination */
  1623. X    init_match(player, to, TYPE_PLAYER);
  1624. X    match_here();
  1625. X    match_absolute();
  1626. X    if(Wizard(player)) {
  1627. X    match_neighbor();
  1628. X    match_me();
  1629. X    match_player();
  1630. X    }
  1631. X
  1632. X    switch(destination = match_result()) {
  1633. X      case NOTHING:
  1634. X    notify(player, "Send it where?");
  1635. X    break;
  1636. X      case AMBIGUOUS:
  1637. X    notify(player, "I don't know which destination you mean!");
  1638. X    break;
  1639. X      default:
  1640. X    /* check victim, destination types, teleport if ok */
  1641. X    if(Typeof(destination) == TYPE_EXIT
  1642. X       || Typeof(destination) == TYPE_THING
  1643. X       || Typeof(victim) == TYPE_EXIT
  1644. X       || Typeof(victim) == TYPE_ROOM
  1645. X       || (Typeof(victim) == TYPE_PLAYER
  1646. X           && Typeof(destination) != TYPE_ROOM)) {
  1647. X        notify(player, "Bad destination.");
  1648. X#ifndef RESTRICTED_TELEPORT
  1649. X    } else if(!Wizard(player)
  1650. X          && !(Typeof(victim) == TYPE_THING
  1651. X               && Typeof(destination) == TYPE_ROOM
  1652. X               && (controls(player, victim)
  1653. X               || (Typeof(db[victim].location) == TYPE_ROOM
  1654. X                   && controls(player, db[victim].location)))
  1655. X               && (can_link_to(player, TYPE_PLAYER, destination)))) {
  1656. X        notify(player, "Permission denied.");
  1657. X#endif /* RESTRICTED_TELEPORT */          
  1658. X    } else if(Typeof(victim) == TYPE_PLAYER) {
  1659. X        notify(victim, "You feel a wrenching sensation...");
  1660. X        enter_room(victim, destination);
  1661. X        notify(player, "Teleported.");
  1662. X    } else {
  1663. X        /* check for non-sticky dropto */
  1664. X        if(Typeof(destination) == TYPE_ROOM
  1665. X           && db[destination].location != NOTHING
  1666. X           && !(db[destination].flags & STICKY)) {
  1667. X        /* destination has immediate dropto */
  1668. X        destination = db[destination].location;
  1669. X        }
  1670. X
  1671. X        /* do the move */
  1672. X        moveto(victim, destination);
  1673. X        notify(player, "Teleported.");
  1674. X    }
  1675. X    }
  1676. X}
  1677. X
  1678. Xvoid do_mass_teleport(dbref player, const char *arg1)
  1679. X{
  1680. X    dbref victim;
  1681. X    dbref destination;
  1682. X    char buf[BUFFER_LEN];
  1683. X    int moved = 0;
  1684. X
  1685. X    if(!God(player)) {
  1686. X#ifndef TINKER
  1687. X    notify(player, "Only God can do a mass teleport.");
  1688. X#else TINKER
  1689. X    notify(player, "Only the Master Tinker can do a mass teleport.");
  1690. X#endif TINKER
  1691. X    return;
  1692. X    }
  1693. X
  1694. X    /* get destination */
  1695. X    init_match(player, arg1, TYPE_ROOM);
  1696. X    match_here();
  1697. X    match_absolute();
  1698. X
  1699. X    if ((destination = match_result()) == NOTHING) {
  1700. X    notify(player, "Please specify a destination to send everyone to.");
  1701. X    return;
  1702. X    }
  1703. X    
  1704. X    switch (Typeof(destination)) {
  1705. X      case NOTHING:
  1706. X    notify(player, "Send them where?");
  1707. X    break;
  1708. X
  1709. X      case TYPE_ROOM:
  1710. X        for (victim = 0; victim < db_top; victim++) {
  1711. X        if (victim != player && Typeof(victim) == TYPE_PLAYER) {
  1712. X            notify(victim,
  1713. X         "You and everyone around you feels a wrenching sensation...");
  1714. X        moveto(victim, destination);
  1715. X        look_room(victim, destination);
  1716. X        moved++;
  1717. X        }
  1718. X    }
  1719. X    sprintf (buf, "Teleported %d players to %s.",
  1720. X         moved, unparse_object (player, destination));
  1721. X    notify(player, "Teleported.");
  1722. X        break;
  1723. X    
  1724. X      default:
  1725. X    notify(player, "Mass teleports are legal to rooms only.");
  1726. X    }
  1727. X}
  1728. X
  1729. Xvoid do_force(dbref player, const char *what, char *command)
  1730. X{
  1731. X    dbref victim;
  1732. X
  1733. X    if(!Wizard(player)) {
  1734. X    writelog ("FORCE: failed, priv, player %s(%d), who '%s', what '%s'\n",
  1735. X          db[player].name, player, what, command);
  1736. X#ifndef TINKER
  1737. X    notify(player, "Only Wizards may use this command.");
  1738. X#else TINKER
  1739. X    notify(player, "Only Tinkers may use this command.");
  1740. X#endif TINKER
  1741. X    return;
  1742. X    }
  1743. X
  1744. X    /* get victim */
  1745. X    if((victim = lookup_player(what)) == NOTHING) {
  1746. X    writelog ("FORCE: failed, victim, player %s(%d), who '%s', what '%s'\n",
  1747. X          db[player].name, player, what, command);
  1748. X    notify(player, "That player does not exist.");
  1749. X    return;
  1750. X    }
  1751. X
  1752. X#ifdef GOD_PRIV
  1753. X    if(God(victim)) {
  1754. X#ifndef TINKER
  1755. X    writelog ("FORCE: failed, wizard, player %s(%d), who '%s', what '%s'\n",
  1756. X#else TINKER
  1757. X    writelog ("FORCE: failed, tinker, player %s(%d), who '%s', what '%s'\n",
  1758. X#endif TINKER
  1759. X          db[player].name, player, what, command);
  1760. X#ifndef TINKER
  1761. X    notify(player, "You can't force God.");
  1762. X#else TINKER
  1763. X    notify(player, "You can't force the Master Tinker.");
  1764. X#endif TINKER
  1765. X    return;
  1766. X    }
  1767. X#endif GOD_PRIV
  1768. X
  1769. X    /* force victim to do command */
  1770. X    writelog ("FORCE: success, player %s(%d), who '%s', what '%s'\n",
  1771. X          db[player].name, player, what, command);
  1772. X
  1773. X    process_command(victim, command);
  1774. X}
  1775. X
  1776. Xvoid do_stats(dbref player, const char *name)
  1777. X{
  1778. X    dbref rooms;
  1779. X    dbref exits;
  1780. X    dbref things;
  1781. X    dbref players;
  1782. X    dbref total;
  1783. X    dbref i;
  1784. X    dbref owner;
  1785. X    char buf[BUFFER_LEN];
  1786. X
  1787. X    if(!Wizard(player)) {
  1788. X    sprintf(buf, "The universe contains %d objects.", db_top);
  1789. X    notify(player, buf);
  1790. X    } else {
  1791. X    owner = lookup_player(name);
  1792. X    total = rooms = exits = things = players = 0;
  1793. X    for(i = 0; i < db_top; i++) {
  1794. X        if(owner == NOTHING || owner == db[i].owner) {
  1795. X        total++;
  1796. X        switch(Typeof(i)) {
  1797. X          case TYPE_ROOM:
  1798. X            rooms++;
  1799. X            break;
  1800. X          case TYPE_EXIT:
  1801. X            exits++;
  1802. X            break;
  1803. X          case TYPE_THING:
  1804. X            things++;
  1805. X            break;
  1806. X          case TYPE_PLAYER:
  1807. X            players++;
  1808. X            break;
  1809. X          default:
  1810. X            abort();
  1811. X            break;
  1812. X        }
  1813. X        }
  1814. X    }
  1815. X    sprintf(buf,
  1816. X        "%d objects = %d rooms, %d exits, %d things, %d players.",
  1817. X        total, rooms, exits, things, players);
  1818. X    notify(player, buf);
  1819. X#ifdef TEST_MALLOC
  1820. X    sprintf(buf, "Malloc count = %d.", malloc_count);
  1821. X    notify(player, buf);
  1822. X#endif /* TEST_MALLOC */
  1823. X    }
  1824. X}
  1825. X        
  1826. Xvoid do_bobble(dbref player, const char *name, const char *rname)
  1827. X{
  1828. X    dbref victim, recip, i;
  1829. X    char buf[BUFFER_LEN];
  1830. X    int newflags = 0;
  1831. X
  1832. X    if(!Wizard(player)) {
  1833. X#ifndef TINKER
  1834. X        writelog("TOAD: failed, priv %s(%d) who '%s'\n",
  1835. X         db[player].name, player, name);
  1836. X    notify(player, "Only a Wizard can turn a person into a toad.");
  1837. X#else TINKER
  1838. X        writelog("BOBBLE: failed, priv %s(%d) who '%s'\n",
  1839. X         db[player].name, player, name);
  1840. X    notify(player, "Only a Tinker can bobble a person.");
  1841. X#endif TINKER
  1842. X    return;
  1843. X    }
  1844. X
  1845. X    if (!name || !*name) {
  1846. X#ifndef TINKER
  1847. X        writelog("TOAD: failed, syntax %s(%d) who '%s'\n",
  1848. X         db[player].name, player, name);
  1849. X#else TINKER
  1850. X        writelog("BOBBLE: failed, syntax %s(%d) who '%s'\n",
  1851. X         db[player].name, player, name);
  1852. X#endif TINKER
  1853. X    notify(player, "You must specify a victim.");
  1854. X    return;
  1855. X    }
  1856. X    
  1857. X    init_match(player, name, TYPE_PLAYER);
  1858. X    match_neighbor();
  1859. X    match_absolute();
  1860. X    match_player();
  1861. X    if((victim = noisy_match_result()) == NOTHING) {
  1862. X#ifndef TINKER
  1863. X        writelog("TOAD: failed, victim %s(%d) who '%s'\n",
  1864. X         db[player].name, player, name);
  1865. X#else TINKER
  1866. X        writelog("BOBBLE: failed, victim %s(%d) who '%s'\n",
  1867. X         db[player].name, player, name);
  1868. X#endif TINKER
  1869. X    notify(player, "Please specify another victim.");
  1870. X    return;
  1871. X    }
  1872. X
  1873. X#ifdef RECYCLE
  1874. X    /* Default the recipient to RECYCLER */
  1875. X    if (!rname || !*rname || string_compare (rname, RECYCLER) == 0) {
  1876. X    recip = lookup_player(RECYCLER);
  1877. X    newflags = UNWANTED;        /* Can be gotten by other players */
  1878. X    } else {
  1879. X    recip = lookup_player(rname);
  1880. X    }
  1881. X#else
  1882. X    recip = lookup_player(rname);
  1883. X#endif
  1884. X
  1885. X    if(recip == NOTHING || recip == victim) {
  1886. X#ifndef TINKER
  1887. X        writelog("TOAD: failed, recip %s(%d) who '%s'\n",
  1888. X         db[player].name, player, name);
  1889. X#else TINKER
  1890. X        writelog("BOBBLE: failed, recip %s(%d) who '%s'\n",
  1891. X         db[player].name, player, name);
  1892. X#endif TINKER
  1893. X    notify(player, "Please specify another player to own the victim's effects.");
  1894. X    return;
  1895. X    }
  1896. X
  1897. X    if(Typeof(victim) != TYPE_PLAYER) {
  1898. X#ifndef TINKER
  1899. X        writelog("TOAD: failed, type %s(%d) who '%s'\n",
  1900. X         db[player].name, player, name);
  1901. X    notify(player, "You can only turn players into toads!");
  1902. X#else TINKER
  1903. X        writelog("BOBBLE: failed, type %s(%d) who '%s'\n",
  1904. X         db[player].name, player, name);
  1905. X    notify(player, "You can only bobble players!");
  1906. X#endif TINKER
  1907. X    } else if(Wizard(victim)) {
  1908. X#ifndef TINKER
  1909. X        writelog("TOAD: failed, wizard %s(%d) who '%s'\n",
  1910. X         db[player].name, player, name);
  1911. X    notify(player, "You can't turn a Wizard into a toad.");
  1912. X#else TINKER
  1913. X        writelog("BOBBLE: failed, tinker %s(%d) who '%s'\n",
  1914. X         db[player].name, player, name);
  1915. X    notify(player, "You can't bobble a Tinker.");
  1916. X#endif TINKER
  1917. X    } else if(db[victim].contents != NOTHING) {
  1918. X#ifndef TINKER
  1919. X        writelog("TOAD: failed, contents %s(%d) who '%s'\n",
  1920. X         db[player].name, player, name);
  1921. X#else TINKER
  1922. X        writelog("BOBBLE: failed, contents %s(%d) who '%s'\n",
  1923. X         db[player].name, player, name);
  1924. X#endif TINKER
  1925. X
  1926. X    notify(player, "What about what they are carrying?");
  1927. X    } else {
  1928. X#ifndef TINKER
  1929. X        writelog("TOAD: success %s(%d) who '%s'\n",
  1930. X         db[player].name, player, name);
  1931. X#else TINKER
  1932. X        writelog("BOBBLE: success %s(%d) who '%s'\n",
  1933. X         db[player].name, player, name);
  1934. X#endif TINKER
  1935. X
  1936. X    /* we are ok */
  1937. X    /* do it */
  1938. X    if(db[victim].password) {
  1939. X        free((void *) db[victim].password);
  1940. X        db[victim].password = 0;
  1941. X    }
  1942. X    db[victim].flags = TYPE_THING;
  1943. X
  1944. X    /* Give the sphere and all old belongings to recipient */
  1945. X    db[victim].owner = recip;
  1946. X    for (i=0; i<db_top; i++) {
  1947. X        if (db[i].owner == victim) {
  1948. X        db[i].owner = recip;
  1949. X        db[i].flags |= newflags;
  1950. X        }
  1951. X    }
  1952. X
  1953. X    db[victim].pennies = 1;    /* dont let him keep his immense wealth */
  1954. X
  1955. X    /* notify people */
  1956. X#ifndef TINKER
  1957. X    sprintf(buf, "You have been turned into a toad by %s.",
  1958. X        db[player].name);
  1959. X#else TINKER
  1960. X    sprintf(buf, "You have been encased in a stasis sphere by %s.",
  1961. X        db[player].name);
  1962. X#endif TINKER
  1963. X    notify(victim, buf);
  1964. X#ifndef TINKER
  1965. X    sprintf(buf, "You turned %s into a toad!", db[victim].name);
  1966. X#else TINKER
  1967. X    sprintf(buf, "You bobbled %s!", db[victim].name);
  1968. X#endif TINKER
  1969. X    notify(player, buf);
  1970. X
  1971. X    /* reset name */
  1972. X#ifdef PLAYER_LIST
  1973. X    delete_player(victim);
  1974. X#endif PLAYER_LIST    
  1975. X#ifndef TINKER
  1976. X    sprintf(buf, "a slimy toad named %s", db[victim].name);
  1977. X#else TINKER
  1978. X    sprintf(buf, "a silvery sphere containing %s", db[victim].name);
  1979. X#endif TINKER
  1980. X    free((void *) db[victim].name);
  1981. X    db[victim].name = alloc_string(buf);
  1982. X    }
  1983. X}
  1984. X
  1985. Xvoid do_unbobble(dbref player, const char *name, const char *newname)
  1986. X{
  1987. X    dbref victim;
  1988. X    char buf[BUFFER_LEN];
  1989. X
  1990. X    if(!Wizard(player)) {
  1991. X#ifndef TINKER
  1992. X        writelog("UNTOAD: failed, priv %s(%d) who '%s'\n",
  1993. X         db[player].name, player, name);
  1994. X    notify(player, "Only a Wizard can turn a toad into a person.");
  1995. X#else TINKER
  1996. X        writelog("UNBOBBLE: failed, priv %s(%d) who '%s'\n",
  1997. X         db[player].name, player, name);
  1998. X    notify(player, "Only a Tinker can unbobble a person.");
  1999. X#endif TINKER
  2000. X    return;
  2001. X    }
  2002. X
  2003. X    if (!name || !*name) {
  2004. X#ifndef TINKER
  2005. X        writelog("UNTOAD: failed, syntax %s(%d) who '%s'\n",
  2006. X         db[player].name, player, name);
  2007. X#else TINKER
  2008. X        writelog("UNBOBBLE: failed, syntax %s(%d) who '%s'\n",
  2009. X         db[player].name, player, name);
  2010. X#endif TINKER
  2011. X    notify(player, "You must specify a thing.");
  2012. X    return;
  2013. X    }
  2014. X    
  2015. X    if (!newname || !*newname) {
  2016. X#ifndef TINKER
  2017. X        writelog("UNTOAD: failed, syntax %s(%d) who '%s'\n",
  2018. X         db[player].name, player, name);
  2019. X    notify(player,"You must specify a new name: @untoad <thing> = <name>");
  2020. X#else TINKER
  2021. X        writelog("UNBOBBLE: failed, syntax %s(%d) who '%s'\n",
  2022. X         db[player].name, player, name);
  2023. X    notify(player,
  2024. X           "You must specify a new name: @unbobble <thing> = <name>");
  2025. X#endif TINKER
  2026. X    return;
  2027. X    }
  2028. X    
  2029. X    init_match(player, name, TYPE_THING);
  2030. X    match_neighbor();
  2031. X    match_absolute();
  2032. X    match_player();
  2033. X    if((victim = noisy_match_result()) == NOTHING) {
  2034. X#ifndef TINKER
  2035. X        writelog("UNTOAD: failed, victim %s(%d) who '%s'\n",
  2036. X         db[player].name, player, name);
  2037. X#else TINKER
  2038. X        writelog("UNBOBBLE: failed, victim %s(%d) who '%s'\n",
  2039. X         db[player].name, player, name);
  2040. X#endif TINKER
  2041. X    notify(player, "Please specify another thing.");
  2042. X    return;
  2043. X    }
  2044. X
  2045. X    if(Typeof(victim) != TYPE_THING) {
  2046. X#ifndef TINKER
  2047. X        writelog("UNTOAD: failed, type %s(%d) who '%s'\n",
  2048. X         db[player].name, player, name);
  2049. X    notify(player, "You can only turn players into toads!");
  2050. X#else TINKER
  2051. X        writelog("UNBOBBLE: failed, type %s(%d) who '%s'\n",
  2052. X         db[player].name, player, name);
  2053. X    notify(player, "You can only bobble players!");
  2054. X#endif TINKER
  2055. X    } else if (!ok_player_name(newname)) {
  2056. X#ifndef TINKER
  2057. X        writelog("UNTOAD: failed, name %s(%d) who '%s'\n",
  2058. X         db[player].name, player, name);
  2059. X#else TINKER
  2060. X        writelog("UNBOBBLE: failed, name %s(%d) who '%s'\n",
  2061. X         db[player].name, player, name);
  2062. X#endif TINKER
  2063. X    notify(player, "You can't give a player that name!");
  2064. X    } else {
  2065. X#ifndef TINKER
  2066. X        writelog("UNTOAD: success %s(%d) who '%s'\n",
  2067. X         db[player].name, player, name);
  2068. X#else TINKER
  2069. X        writelog("UNBOBBLE: success %s(%d) who '%s'\n",
  2070. X         db[player].name, player, name);
  2071. X#endif TINKER
  2072. X
  2073. X    /* we are ok */
  2074. X    /* do it */
  2075. X    db[victim].flags = TYPE_PLAYER;
  2076. X    db[victim].owner = victim;
  2077. X    db[victim].pennies = KILL_BONUS;
  2078. X
  2079. X    /* reset name */
  2080. X    free((void *) db[victim].name);
  2081. X    db[victim].name = alloc_string(newname);
  2082. X
  2083. X#ifndef TINKER
  2084. X    sprintf(buf, "You turned the toad back into %s!", db[victim].name);
  2085. X#else TINKER
  2086. X    sprintf(buf, "You unbobbled %s!", db[victim].name);
  2087. X#endif TINKER
  2088. X    notify(player, buf);
  2089. X
  2090. X    sprintf(buf, "Use @newpassword to give %s a password",
  2091. X        db[victim].name);
  2092. X    notify(player, buf);
  2093. X
  2094. X#ifdef PLAYER_LIST
  2095. X    add_player(victim);
  2096. X#endif PLAYER_LIST    
  2097. X    }
  2098. X}
  2099. X
  2100. Xvoid do_newpassword(dbref player, const char *name, const char *password)
  2101. X{
  2102. X    dbref victim;
  2103. X    char buf[BUFFER_LEN];
  2104. X
  2105. X    if(!Wizard(player)) {
  2106. X        writelog("PASSWORD: failed, priv %s(%d) who '%s'\n",
  2107. X         db[player].name, player, name);
  2108. X    notify(player, "Your delusions of grandeur have been duly noted.");
  2109. X    return;
  2110. X    } else if((victim = lookup_player(name)) == NOTHING) {
  2111. X        writelog("PASSWORD: failed, victim %s(%d) who '%s'\n",
  2112. X         db[player].name, player, name);
  2113. X    notify(player, "No such player.");
  2114. X    } else if(*password != '\0' && !ok_password(password)) {
  2115. X    /* Wiz can set null passwords, but not bad passwords */
  2116. X        writelog("PASSWORD: failed, password %s(%d) who '%s'\n",
  2117. X         db[player].name, player, name);
  2118. X    notify(player, "Bad password");
  2119. X#ifdef GOD_PRIV    
  2120. X    } else if (God(victim) && !God(player)) {
  2121. X#ifndef TINKER
  2122. X        writelog("PASSWORD: failed, wizard %s(%d) who '%s'\n",
  2123. X#else TINKER
  2124. X        writelog("PASSWORD: failed, tinker %s(%d) who '%s'\n",
  2125. X#endif TINKER
  2126. X         db[player].name, player, name);
  2127. X    notify(player, "You cannot change that player's password.");
  2128. X#endif GOD_PRIV    
  2129. X    } else {
  2130. X        writelog("PASSWORD: success %s(%d) who '%s'\n",
  2131. X         db[player].name, player, name);
  2132. X    /* it's ok, do it */
  2133. X    if(db[victim].password) free((void *) db[victim].password);
  2134. X    db[victim].password = alloc_string(password);
  2135. X    notify(player, "Password changed.");
  2136. X    sprintf(buf, "Your password has been changed by %s.", db[player].name);
  2137. X    notify(victim, buf);
  2138. X    }
  2139. X}
  2140. X
  2141. Xvoid do_boot(dbref player, const char *name)
  2142. X{
  2143. X    dbref victim;
  2144. X    char buf[BUFFER_LEN];
  2145. X
  2146. X    if(!Wizard(player)) {
  2147. X    writelog ("BOOT: failed, priv player %s(%d), who '%s'\n",
  2148. X          db[player].name, player, name);
  2149. X
  2150. X#ifndef TINKER
  2151. X    notify(player, "Only a Wizard can boot another player off!");
  2152. X#else TINKER
  2153. X    notify(player, "Only a Tinker can boot another player off!");
  2154. X#endif TINKER
  2155. X    return;
  2156. X    }
  2157. X
  2158. X    init_match(player, name, TYPE_PLAYER);
  2159. X    match_neighbor();
  2160. X    match_absolute();
  2161. X    match_player();
  2162. X    if((victim = noisy_match_result()) == NOTHING) return;
  2163. X
  2164. X#ifdef GOD_PRIV
  2165. X    if(God(victim)) {
  2166. X#ifndef TINKER
  2167. X    writelog ("BOOT: failed, wizard, player %s(%d), who '%s'\n",
  2168. X#else TINKER
  2169. X    writelog ("BOOT: failed, tinker, player %s(%d), who '%s'\n",
  2170. X#endif TINKER
  2171. X          db[player].name, player, name);
  2172. X
  2173. X    notify(player, "You can't boot that player!");
  2174. X    return;
  2175. X    }
  2176. X#endif GOD_PRIV
  2177. X
  2178. X    if(Typeof(victim) != TYPE_PLAYER) {
  2179. X    writelog ("BOOT: failed, victim, player %s(%d), who '%s'\n",
  2180. X          db[player].name, player, name);
  2181. X
  2182. X    notify(player, "You can only boot off other players!");
  2183. X    } else {
  2184. X    writelog ("BOOT: success, player %s(%d), who '%s'\n",
  2185. X          db[player].name, player, name);
  2186. X
  2187. X    /* we are ok */
  2188. X    /* do it */
  2189. X    /* notify people */
  2190. X    sprintf(buf, "You have been booted off the game by %s.",
  2191. X        db[player].name);
  2192. X    notify(victim, buf);
  2193. X    sprintf(buf, "You booted %s off!", db[victim].name);
  2194. X    notify(player, buf);
  2195. X    boot_off(victim);
  2196. X    /* reset name */
  2197. X    }
  2198. X}
  2199. END_OF_FILE
  2200. if test 16849 -ne `wc -c <'wiz.c'`; then
  2201.     echo shar: \"'wiz.c'\" unpacked with wrong size!
  2202. fi
  2203. # end of 'wiz.c'
  2204. fi
  2205. echo shar: End of archive 5 \(of 10\).
  2206. cp /dev/null ark5isdone
  2207. MISSING=""
  2208. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  2209.     if test ! -f ark${I}isdone ; then
  2210.     MISSING="${MISSING} ${I}"
  2211.     fi
  2212. done
  2213. if test "${MISSING}" = "" ; then
  2214.     echo You have unpacked all 10 archives.
  2215.     echo ">>> now type 'sh joinspl.sh'"
  2216.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2217. else
  2218.     echo You still need to unpack the following archives:
  2219.     echo "        " ${MISSING}
  2220. fi
  2221. ##  End of shell archive.
  2222. exit 0
  2223.